library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.all;
use constants.all;
use sram_emu.all;

entity cpu_mem_wrapper_tb is
		generic(
		sramAddrWd : natural range 2 to 32 := 32;
		sramDataWd : natural range 2 to 32 := 32 );
end cpu_mem_wrapper_tb;

architecture cpu_mem_wrapper_tb_arch of cpu_mem_wrapper_tb is

	signal clock, reset, nWE, nOE : std_logic;
	signal addr: std_logic_vector(sramAddrWd-1 downto 0);
	signal data: std_logic_vector(sramDataWd-1 downto 0);	

	constant cycleTime : time := 10 ns;
	constant resetTime : time := (cycleTime * 2);
	
	type MemArrayType is array(0 to 32) of b32;
	signal mem1 : MemArrayType := 	
	(
	-- condition & class    & unused & function           & immB &	opA     & opB    & opC
	 -- move 0 to r0			   by alu 1st byte is "write back"
	 COND_ALWAYS & CLASS_ALU & UNUSED4 & ('1' & ALU_PASS_B) & '1'  & "-----" & "01100" & r0,
	 COND_ALWAYS & CLASS_ALU & UNUSED4 & ('1' & ALU_ADD) 	& '0'  & r0		 & r0 & r0,
	 -- mov 3 to r2
	 COND_ALWAYS & CLASS_ALU & UNUSED4 & ('1' & ALU_PASS_B) & '1'  & "-----" & "00011" & r2,	 	 
	 -- store r2 at r0
	 COND_ALWAYS & CLASS_LDST & UNUSED4 & F_LDST_STORE      & '0'  & r0      & r2      & "-----",
	 
	 -- compare instruction example -> write back bit is set to 0
	 COND_ALWAYS & CLASS_ALU  & UNUSED4 & ('0' & ALU_SUB )  & '0'  & r1      & r2      & "-----",
	
	 COND_ALWAYS & CLASS_LDST & UNUSED4 & F_LDST_LOAD      & '0'  & r0       & "-----" & r3,
	
	 -- absolute jump to address 00000
	 COND_ALWAYS & CLASS_JUMP & UNUSED4 & F_JUMP_ABS        & '1'  & r0      & "00000" & r0,	 
	--
--	 COND_ALWAYS & CLASS_ALU  & UNUSED4 & ('0' & ALU_SUB )  & '0'  & r1      & r2      & "-----",
--	 -- relative jump to (PC - 3)
--	 COND_EQUAL & CLASS_JUMP  & UNUSED4 & F_JUMP_ABS        & '1'  & "-----" & "11101" & r0,
--	 
	 others => x"00000000"
	);
	
begin		
	cpuMemWrapperC: entity work.cpu_mem_wrapper 
		generic map(sramAddrWd => sramAddrWd, sramDataWd => sramDataWd)
		port map (
			clock => clock,
			reset => reset,
			sram_nWE => nWE,
			sram_nOE => nOE,
			sramAddr => addr,
			sramData => data
		);
	-- when we'll get the assemler, we can test with binary files		
	--sramC: entity sram port map(nCS => nCS, nWE => nWE, nOE => nOE, 
	--	addr => addr, data => data);		
		
	clock <= not clock after cycleTime / 2; 
	reset <= '1', '0' after resetTime; 
	
	sramTest: process
		procedure test1 is
			variable intAddr : integer;
		begin				
			wait for resetTime;
			loop
				intAddr := to_integer(unsigned(addr));
				if nOE = '0' then -- output enable active? -- load operation
					if(intAddr < mem1'length) then				
						data <= mem1(intAddr);
					else
						data <= (others => 'Z');
					end if;
				elsif nWE = '0' then -- write enable active? -> store operation
					if(intAddr < mem1'length) then				
						mem1(intAddr) <= data;
					end if;				
				end if;
				wait for cycleTime;
	        end loop;
		end procedure test1;	
	begin
		wait for resetTime;
		test1;
		wait;
	end process sramTest;
	

end cpu_mem_wrapper_tb_arch;

